package com.hfxt.j96springboot.web.shiro;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;

@Configuration
public class ShiRoConfig {

    /**
     * 等价于 web.xml配置
     * <filter>
     * <filter-name>shiRoFilter</filter-name>
     * <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
     * <init-param>
     * <param-name>targetFilterLifecycle</param-name>
     * <param-value>true</param-value>
     * </init-param>
     * </filter>
     * <filter-mapping>
     * <filter-name>shiRoFilter</filter-name>
     * <url-pattern>/*</url-pattern>
     * </filter-mapping>
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean webShiRoFilter() {
        FilterRegistrationBean frb = new FilterRegistrationBean();
        DelegatingFilterProxy dfp = new DelegatingFilterProxy();
        frb.setFilter(dfp);
        frb.setName("shiRoFilter");
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();
        linkedHashSet.add("/*");
        frb.setUrlPatterns(linkedHashSet);
        Map<String, String> initParameters = new HashMap<String, String>();
        initParameters.put("targetFilterLifecycle", "true");
        frb.setInitParameters(initParameters);
        return frb;
    }

    /**
     * 凭证匹配器
     * （由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
     * ）
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher
                = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(1024);//散列的次数，比如散列两次，相当于 md5(md5(""));
        return hashedCredentialsMatcher;
    }

    /**
     * 配置我的realm
     *
     * @return
     */
    @Bean
    public Realm myRealm() {
        UserRealm myShiroRealm =new UserRealm();
       myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        //如果数据库的密码是加密的 需要注释的密码认证 （把注释去掉即可）
       // return new UserRealm();
        return  myShiroRealm;
    }

    /**
     * 定义默认的securityManager
     *
     * @return  DefaultWebSecurityManager
     */
    @Bean
    public DefaultWebSecurityManager securityManager
    (@Autowired Realm myRealm) {
        DefaultWebSecurityManager dwm = new DefaultWebSecurityManager();
        dwm.setRealm(myRealm);
        return dwm;
    }

    /**
     * 定义和过滤器一致名字的shiRoFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiRoFilter
    (@Autowired SecurityManager securityManager) {
        ShiroFilterFactoryBean filterFactoryBean
                = new ShiroFilterFactoryBean();
        filterFactoryBean.setSecurityManager(securityManager);

//      如果需要授权就跳转到这个路径
        filterFactoryBean.setLoginUrl("/login/tologin");
//      如果没有权限就跳转到这个路径
        filterFactoryBean.setUnauthorizedUrl("login/403");

//      自定义一个过滤器  filterChainDefinitions
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
        filterChainDefinitionMap.put("/statics/**", "anon"); //静态资源
        filterChainDefinitionMap.put("/login/**", "anon");
        filterChainDefinitionMap.put("/shop/**", "authc,roles[buyer]");  //要具备什么角色
        filterChainDefinitionMap.put("/student/**", "anon");
        filterChainDefinitionMap.put("/stu/**", "authc");
       // filterChainDefinitionMap.put("/index/**", "authc,roles[buyer]");
        filterChainDefinitionMap.put("/index.jsp", "authc,roles[buyer,operator]");
        // filterChainDefinitionMap.put("/success.jsp", "authc,zqRoles[buyer,seller]");

        Map<String,Filter> filterMap=new LinkedHashMap<>();
        filterMap.put("zqRoles",new CustomRolesAuthorizationFilter());
        filterFactoryBean.setFilters(filterMap);

        //必须同时具备
        filterChainDefinitionMap.put("/success.jsp", "authc,zqRoles[operator,seller]");

        //主要这行代码必须放在所有权限设置的最后，不然会导致所有 url 都被拦截 剩余的都需要认证
       // filterChainDefinitionMap.put("/**", "authc");
        filterFactoryBean.setFilterChainDefinitionMap
                (filterChainDefinitionMap);
        return filterFactoryBean;

    }

    /**
     * 定义ShiRo的生命周期
     *
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }


}